#include <symboles.h>

#include <stdio.h>
#include <stdlib.h>

struct Symbole* symBase = NULL;
struct Symbole* symTete = NULL;

int symAdd(char* nom, int consta){
	struct Symbole* verif = symBase;
	while(verif != NULL){
		if(strcmp(verif->nom, nom)==0) return ERR_REDEFINITION;
		verif = verif->pNext;
	}

	if(symBase == NULL){
		symBase = symTete = malloc(sizeof(struct Symbole));
		symTete->rang = 0;
		symTete->pNext = NULL;
		symTete->consta = consta;
		strcpy(&(symTete->nom), nom);
	}else{
		unsigned int r = symTete->rang;
		symTete->pNext = malloc(sizeof(struct Symbole));
		symTete = symTete->pNext;
		symTete->rang = r+1;
		symTete->pNext = NULL;
		symTete->consta = consta;
		strcpy(&(symTete->nom), nom);
	}
	return 0;
}

int symExist(char* nom){
	struct Symbole* verif = symBase;
	while(verif != NULL){
		if(strcmp(verif->nom, nom)==0){
			return 1;
		}
		verif = verif->pNext;
	}
	return 0;
}

int symIndex(char* nom){
	struct Symbole* verif = symBase;
	int i = 0;
	while(verif != NULL){
		if(strcmp(verif->nom, nom)==0){
			return i;
		}
		verif = verif->pNext;
		++i;
	}
	return -33;
}

int symType(char* nom){
	struct Symbole* verif = symBase;
	while(verif != NULL){
		if(strcmp(verif->nom, nom)==0){
			return verif->type;
		}
		verif = verif->pNext;
	}
	return -33;
}

int symConst(char* nom){
	struct Symbole* verif = symBase;
	while(verif != NULL){
		if(strcmp(verif->nom, nom)==0){
			return verif->consta;
		}
		verif = verif->pNext;
	}
	return -33;
}

void symSetConstEntier(int val){
	symTete->type = TYPE_CONST_ENTIER;
	int* ptr = malloc(sizeof(int));
	*ptr = val;
	symTete->valeur = (void *) ptr;
}

void symSetVarEntier(int val){
	symTete->type = TYPE_VAR_ENTIER;
	int* ptr = malloc(sizeof(int));
	*ptr = val;
	symTete->valeur = (void *) ptr;
}

void symSetConstReel(double val){
	symTete->type = TYPE_CONST_REEL;
	double* ptr = malloc(sizeof(double));
	*ptr = val;
	symTete->valeur = (void *) ptr;
}

void symSetVarReel(double val){
	symTete->type = TYPE_VAR_REEL;
	double* ptr = malloc(sizeof(double));
	*ptr = val;
	symTete->valeur = (void *) ptr;
}

void symSetConstBool(int val){
	symTete->type = TYPE_CONST_BOOL;
	int* ptr = malloc(sizeof(int));
	*ptr = (val!=0);
	symTete->valeur = (void *) ptr;
}

void symSetVarBool(int val){
	symTete->type = TYPE_VAR_BOOL;
	int* ptr = malloc(sizeof(int));
	*ptr = (val!=0);
	symTete->valeur = (void *) ptr;
}

void symSetConstChaine(char* val){
	symTete->type = TYPE_CONST_CHAINE;
	char* ptr = malloc(sizeof(char)*(strlen(val)+1));
	strcpy(ptr, val);
	symTete->valeur = (void *) ptr;
}

void symSetVarChaine(char* val){
	symTete->type = TYPE_VAR_CHAINE;
	char* ptr = malloc(sizeof(char)*(strlen(val)+1));
	strcpy(ptr, val);
	symTete->valeur = (void *) ptr;
}

void symSetConstChar(char val){
	symTete->type = TYPE_CONST_CHAR;
	char* ptr = malloc(sizeof(char));
	*ptr = val;
	symTete->valeur = (void *) ptr;
}

void symSetVarChar(char val){
	symTete->type = TYPE_VAR_CHAR;
	char* ptr = malloc(sizeof(char));
	*ptr = val;
	symTete->valeur = (void *) ptr;
}

void symPrint(FILE* pF){
	struct Symbole* p = symBase;
	while(p != NULL){
		fprintf(pF, "rang %d; nom %s; type %d; const %d; valeur ", p->rang, p->nom, p->type, p->consta);

		unsigned int t = p->type;
		if(t == TYPE_CONST_ENTIER || t == TYPE_VAR_ENTIER){
			int* pI = (int*) p->valeur;
			fprintf(pF, "%d", *pI);
		}else if(t == TYPE_CONST_REEL || t == TYPE_VAR_REEL){
			double* pFl = (double*) p->valeur;
			fprintf(pF, "%g", *pFl);		
		}else if(t == TYPE_CONST_BOOL || t == TYPE_VAR_BOOL){
			int* pI = (int*) p->valeur;
			fprintf(pF, "%d", *pI);
		}else if(t == TYPE_CONST_CHAINE || t == TYPE_VAR_CHAINE){
			char* pS = (char*) p->valeur;
			fprintf(pF, "%s", pS);
		}else if(t == TYPE_CONST_CHAR || t == TYPE_VAR_CHAR){
			char* pS = (char*) p->valeur;
			fprintf(pF, "%c", *pS);
		}
		
		fprintf(pF, "\n");
		fflush(pF);		
		
		p = p->pNext;
	}
}

void symTable(FILE* pF){
	struct Symbole* p = symBase;
	while(p != NULL){
		char typec[20] = "";
		unsigned int t = p->type;
		if(t == TYPE_CONST_ENTIER || t == TYPE_VAR_ENTIER){
			if(p->consta == 0)
				strcpy(typec, "v_int");
			else
				strcpy(typec, "c_int");
		}else if(t == TYPE_CONST_REEL || t == TYPE_VAR_REEL){
			if(p->consta == 0)
				strcpy(typec, "v_double");
			else
				strcpy(typec, "c_double");		
		}else if(t == TYPE_CONST_BOOL || t == TYPE_VAR_BOOL){
			if(p->consta == 0)
				strcpy(typec, "v_bool");
			else
				strcpy(typec, "c_bool");	
		}else if(t == TYPE_CONST_CHAINE || t == TYPE_VAR_CHAINE){
			if(p->consta == 0)
				strcpy(typec, "v_string");
			else
				strcpy(typec, "c_string");	
		}else if(t == TYPE_CONST_CHAR || t == TYPE_VAR_CHAR){
			if(p->consta == 0)
				strcpy(typec, "v_char");
			else
				strcpy(typec, "c_char");	
		}
		fprintf(pF, "%%%% %s %s\n", p->nom, typec);
		fflush(pF);		
		
		p = p->pNext;
	}
}

void symFree(){
	struct Symbole* p = symBase;
	struct Symbole* tmp;
	while(p != NULL){
		tmp = p->pNext;
		free(p->valeur);
		free(p);
		p = tmp;
	}
	
	symBase = symTete = NULL;
}
